﻿namespace DeltaGroup.WheelOfJeopardy.ChallengeManager
{
    using System.Collections.Generic;

    using DeltaGroup.WheelOfJeopardy.Model;

    /// <summary>
    /// Abstract algorithm strategy signature
    /// </summary>
    public abstract class InterpreterStrategy
    {
        #region Fields

        private List<string> stopWordList = StopWords.BaseWordList;

        #endregion Fields

        #region Properties

        /// <summary>
        /// Gets or sets the stop word list.
        /// </summary>
        /// <value>The stop word list.</value>
        public virtual List<string> StopWordList
        {
            get { return stopWordList; }
            protected set { stopWordList = value; }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Creates the strategy.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <returns></returns>
        public static InterpreterStrategy CreateStrategy(DifficultyLevel level)
        {
            InterpreterStrategy strategy;
            switch (level) {
                case DifficultyLevel.Easy:
                    strategy = new RelaxedStrategy();
                    break;
                case DifficultyLevel.Medium :
                    strategy = new ModerateStrategy();
                    break;
                default :
                    strategy = new StrictStrategy();
                    break;
            }

            return strategy;
        }

        /// <summary>
        /// Evaluates the response.
        /// </summary>
        /// <param name="challenge">The challenge.</param>
        /// <param name="responseString">The response string.</param>
        /// <returns></returns>
        public abstract bool EvaluateResponse(Challenge challenge, string responseString);

        /// <summary>
        /// Checks for an exact string match.
        /// </summary>
        /// <param name="expected">The expected.</param>
        /// <param name="actual">The actual.</param>
        /// <returns></returns>
        protected virtual bool ExactCheck(string expected, string actual)
        {
            return expected.Equals(actual);
        }

        /// <summary>
        /// Performs an ordered token match check.
        /// </summary>
        /// <param name="expectedResponse">The expected response.</param>
        /// <param name="actualResponse">The actual response.</param>
        /// <returns></returns>
        protected virtual bool OrderedTokenCheck(Phrase expectedResponse, Phrase actualResponse)
        {
            IEqualityComparer<Phrase> iecExpected = expectedResponse as IEqualityComparer<Phrase>;
            return iecExpected.Equals(expectedResponse, actualResponse);
        }

        /// <summary>
        /// Checks all expected tokens for matches including synonyms.
        /// </summary>
        /// <param name="expectedResponse">The expected response.</param>
        /// <param name="actualResponse">The actual response.</param>
        /// <param name="synonymList">The synonym list.</param>
        /// <returns></returns>
        protected virtual PhraseMatchResult SynonymMatchCheck(Phrase expectedResponse, Phrase actualResponse, List<Synonym> synonymList)
        {
            PhraseMatchResult matchResult = new PhraseMatchResult();
            IEqualityComparer<string> comparer = new SynonymComparer(synonymList);

            foreach (string token in actualResponse)
            {
                if (expectedResponse.Contains(token, comparer))
                {
                    matchResult.Matches.Add(token);
                }
                else
                {
                    matchResult.Misses.Add(token);
                }
            }

            return matchResult;
        }

        #endregion Methods
    }
}